package com.hung.pro.iFlashCards;

import com.hung.pro.iFlashCards.bean.CardBean;
import com.hung.pro.iFlashCards.bean.LexiconBean;
import com.hung.pro.iFlashCards.component.VocabularyTableModel;
import com.hung.pro.iFlashCards.dao.CardBeanDao;
import com.hung.pro.iFlashCards.dao.LexiconBeanDao;
import com.hung.pro.iFlashCards.ui.Resources;
import com.hung.pro.iFlashCards.ui.UIHelper;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.uif_lite.panel.SimpleInternalFrame;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;


/**
 * Created by IntelliJ IDEA.
 * User: hung
 * Date: 2008/05/04
 * Time: 9:25:35
 * To change this template use File | Settings | File Templates.
 */
public class EditVocabularyWindow extends JDialog implements ActionListener {
    private JPanel mainPanel;
    private JToolBar toolBar;
    private JScrollPane scrollPane;
    private JTable cardTable;
    private VocabularyTableModel dataModel;
    private int currentLexiconId = -1;

    /**
     * LexiconBeanDao
     */
    private static LexiconBeanDao lexiconDao = new LexiconBeanDao();

    /**
     * CardBeanDao
     */
    private static CardBeanDao cardDao = new CardBeanDao();

    public EditVocabularyWindow() {


    }

    private void createUIComponents() {
        toolBar = new JToolBar();
        toolBar.setFloatable(false);
        toolBar.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
        buildToolBar();
        buildCardTable();
        configureUI();
        //load cards
        loadCardsByLexicon(currentLexiconId);

    }

    private void configureUI() {
        try {
            String selectedLaf = UIManager.getSystemLookAndFeelClassName();
            UIManager.setLookAndFeel(selectedLaf);
        } catch (Exception e) {
            System.out.println("Can't change L&F: " + e);
        }

    }

    /**
     * build toolbar
     */
    private void buildToolBar() {
        AbstractButton doneButton = UIHelper.createToolBarButton("back.png", "Back", Resources.getString("tooltip.vocabwindow.turnback"));
        doneButton.addActionListener(this);
        UIHelper.setKeyAcceleratorForButton(doneButton, KeyStroke.getKeyStroke("ctrl B"), new DoneButtonAction());
        toolBar.add(doneButton);
        toolBar.addSeparator();
        AbstractButton addButton = UIHelper.createToolBarButton("add.png", "Add", Resources.getString("tooltip.vocabwindow.add"));
        addButton.addActionListener(new AddButtonActionListener());
        UIHelper.setKeyAcceleratorForButton(addButton, KeyStroke.getKeyStroke("ctrl N"), new AddButtonAction());
        toolBar.add(addButton);
        toolBar.addSeparator();
        AbstractButton deleteButton = UIHelper.createToolBarButton("delete.png", "Delete", Resources.getString("tooltip.vocabwindow.delete"));
        deleteButton.addActionListener(new DeleteButtonActionListener());
        UIHelper.setKeyAcceleratorForButton(deleteButton, KeyStroke.getKeyStroke("ctrl D"), new DeleteButtonAction());
        toolBar.add(deleteButton);
        //Add lexicon list
        toolBar.addSeparator(new Dimension(5, 1));
        //add Label
        toolBar.add(new JLabel(Resources.getString("label.lexicon"), JLabel.LEFT));
        toolBar.add(Box.createHorizontalStrut(5));
        toolBar.add(buildLexiconCombobox());
        //add info button to the left side
        toolBar.add(Box.createHorizontalGlue());
        AbstractButton helpButton = UIHelper.createToolBarButton("help.png", "Help", Resources.getString("tooltip.vocabwindow.help"));
        helpButton.addActionListener(new HelpButtonActionListener());
        toolBar.add(helpButton);
        // toolBar.add(UIHelper.createToolBarButton("info.png", "Info"));
    }

    /**
     * Build lexicon list combobox
     */
    private JComponent buildLexiconCombobox() {
        //Lexicon list
        try {
            List<LexiconBean> lexiconList = lexiconDao.getLexicon();
            JComboBox lexiconCombo = new JComboBox(lexiconList.toArray());
            lexiconCombo.setToolTipText(Resources.getString("tooltip.vocabwindow.combo"));
            lexiconCombo.setFocusable(true);
            lexiconCombo.addActionListener(new LexiconComboActionListener());
            //update current lexiconId
            if (lexiconList.size() > 0) {
                if (currentLexiconId == -1) {
                    currentLexiconId = lexiconList.get(0).getId();
                } else {
                    //update selected index
                    int size = lexiconList.size();
                    for (int i = 0; i < size; i++) {
                        LexiconBean lexicon = lexiconList.get(i);
                        if (currentLexiconId == lexicon.getId()) {
                            lexiconCombo.setSelectedIndex(i);
                        }
                    }
                }
            } else {
                //disable button
                enableToolBarButton("Add", false);
                enableToolBarButton("Delete", false);

            }
            return lexiconCombo;

        } catch (Exception e) {
            String error = e.getLocalizedMessage();
            JOptionPane.showMessageDialog(mainPanel.getParent(), error, "Error", JOptionPane.WARNING_MESSAGE);
            e.printStackTrace();
        }
        //on error, return blank combo
        JComboBox blankCombo = new JComboBox();
        blankCombo.setFocusable(false);
        return blankCombo;
    }

    /**
     * Build card table
     */
    private void buildCardTable() {
        dataModel = new VocabularyTableModel();

        //cardTable = new JTable(dataModel);
        cardTable = new JTable(dataModel) {
            public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
                super.changeSelection(rowIndex, columnIndex, toggle, extend);
                if (cardTable.editCellAt(rowIndex, columnIndex)) {
                    cardTable.getEditorComponent().requestFocusInWindow();
                }
            }
        };
        //setting for card table
        //disable drag header
        cardTable.getTableHeader().setReorderingAllowed(false);
        //use VocabularyCellEditor to validate word
        int vColIndex = VocabularyTableModel.COLUMN_WORD_INDEX;
        TableColumn col = cardTable.getColumnModel().getColumn(vColIndex);
        col.setCellEditor(new VocabularyCellEditor(new JTextField()));
        dataModel.addTableModelListener(new CardTableChangeListener());
    }

    /**
     * Load cards information that belonging to the specified lexicon, and display on table
     *
     * @param lexiconId
     */
    private void loadCardsByLexicon(int lexiconId) {
        try {
//load data from db
            List<CardBean> cardList = cardDao.getCardsBelongingToLexicon(lexiconId);
            //clear TableModel Listener first so that no event fired when remove data
            TableModelListener[] modelListeners = dataModel.getTableModelListeners();
            if (modelListeners != null) {
                for (int i = 0; i < modelListeners.length; i++) {
                    dataModel.removeTableModelListener(modelListeners[i]);
                }
            }
            //clear all previous data
            dataModel.clearAll();
            //update table with loaded data
            dataModel.addRows(cardList);
            //add listener
            dataModel.addTableModelListener(new CardTableChangeListener());
            cardTable.updateUI();
        }
        catch (SQLException e) {
            String error = Resources.getString("message.load.card.error");
            JOptionPane.showMessageDialog(mainPanel.getParent(), error, "Error", JOptionPane.WARNING_MESSAGE);
        }
        catch (Exception e) {
            String error = e.getLocalizedMessage();
            JOptionPane.showMessageDialog(mainPanel.getParent(), error, "Error", JOptionPane.WARNING_MESSAGE);
        }

    }

    /**
     * main for test
     */
    public static void main(String[] args) {
        EditVocabularyWindow mainFrame = new EditVocabularyWindow();
        mainFrame.setTitle("Edit Vocabulary");
        mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        SimpleInternalFrame sif = new SimpleInternalFrame("Edit Vocabulary@pro");
        sif.setContent(mainFrame.mainPanel);
        mainFrame.setContentPane(sif);
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        //startup size
        Dimension startupDimension = new Dimension((int) screenSize.getWidth(), (int) (screenSize.getHeight() / 2));
        mainFrame.setMaximumSize(screenSize);
        mainFrame.setPreferredSize(startupDimension);
        mainFrame.setMinimumSize(startupDimension);

        mainFrame.validate();                // Make sure layout is ok
        mainFrame.setVisible(true);

    }

    /**
     * Show window
     */
    public void showWindow() {
        $$$setupUI$$$();
        this.setTitle(Resources.getString("window.title.edit.vocabulary"));
        //set icon
        this.setIconImage(UIHelper.readImageIcon("app.png").getImage());
        this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        SimpleInternalFrame sif = new SimpleInternalFrame("Learn@pro");
        sif.setContent(this.mainPanel);
        this.setContentPane(sif);
        //this.setExtendedState(Frame.MAXIMIZED_BOTH);
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension startupDimension = new Dimension((int) screenSize.getWidth(), (int) (screenSize.getHeight() / 2));
        this.setMaximumSize(screenSize);
        this.setPreferredSize(startupDimension);
        this.setMinimumSize(startupDimension);
        this.setLocale(Resources.getLocale());
        this.setVisible(true);

    }

    /**
     * close the window, when user click done button
     *
     * @param e
     */
    public void actionPerformed(ActionEvent e) {
        dispose();
    }

    public int getCurrentLexiconId() {
        return currentLexiconId;
    }

    public void setCurrentLexiconId(int currentLexiconId) {
        this.currentLexiconId = currentLexiconId;
    }

    {
// GUI initializer generated by IntelliJ IDEA GUI Designer
// >>> IMPORTANT!! <<<
// DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        createUIComponents();
        mainPanel = new JPanel();
        mainPanel.setLayout(new FormLayout("fill:d:grow", "center:34px:noGrow,top:4dlu:noGrow,center:d:grow"));
        CellConstraints cc = new CellConstraints();
        mainPanel.add(toolBar, cc.xy(1, 1, CellConstraints.FILL, CellConstraints.FILL));
        scrollPane = new JScrollPane();
        mainPanel.add(scrollPane, cc.xy(1, 3, CellConstraints.FILL, CellConstraints.FILL));
        scrollPane.setViewportView(cardTable);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return mainPanel;
    }

    /**
     * *********Action Listner***************
     */
    private class LexiconComboActionListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            JComboBox lexiconCombo = (JComboBox) e.getSource();
            LexiconBean lexicon = (LexiconBean) lexiconCombo.getSelectedItem();
            currentLexiconId = lexicon.getId();
            loadCardsByLexicon(currentLexiconId);
        }
    }

    /**
     * Table Data Changed Listener
     */
    private class CardTableChangeListener implements TableModelListener {
        public void tableChanged(TableModelEvent e) {
            //when user add new row, but have not edit anything, then do nothing
            if (e.getType() != TableModelEvent.UPDATE) {
                return;
            }
            int rowIndex = e.getFirstRow();
            VocabularyTableModel model = (VocabularyTableModel) e.getSource();
            CardBean card = model.getRowData(rowIndex);
            //check if word is not null
            if (card.getWord() == null || "".equals(card.getWord().trim())) {
                return;
            }
            //update to db
            try {
                if (card.getId() == -1) {
                    //new card, insert to db
                    int cardId = cardDao.insertCard(card);
                    card.setId(cardId);
                } else {
                    //update existing card
                    cardDao.updateCard(card);
                }
            }
            catch (Exception ex) {
                String error = Resources.getString("message.update.card.error");
                JOptionPane.showMessageDialog(mainPanel.getParent(), error, "Error", JOptionPane.WARNING_MESSAGE);
                ex.printStackTrace();

            }
        }

    }

    /**
     * Add button Action Listener ********
     */
    private class AddButtonActionListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            //clear selection
            cardTable.clearSelection();
            CardBean card = new CardBean();
            card.setId(-1);
            card.setLexiconId(currentLexiconId);
            //card.setWord();
            dataModel.addRow(card);
            cardTable.updateUI();
            //start edit word cell
            cardTable.requestFocus();
            /* cardTable.setColumnSelectionAllowed(true);
            cardTable.setRowSelectionAllowed(true);*/
            int column = dataModel.findColumn(VocabularyTableModel.COLUMN_HEADER_WORD);
            int row = dataModel.getRowCount() - 1;
            System.out.println(String.format("Row: %s, Column:%s", row, column));
            cardTable.changeSelection(row, column, false, false);
            //prevent user click button when did not update the new word that just being added
            enableToolBarButton("Add", false);


        }
    }

    /**
     * Disable toolbar button
     */
    private void enableToolBarButton(String name, boolean isEnabled) {
        Component[] buttons = toolBar.getComponents();
        for (int i = 0; i < buttons.length; i++) {
            if (buttons[i] instanceof AbstractButton) {
                AbstractButton button = (AbstractButton) buttons[i];
                if (name.equals(button.getName())) {
                    button.setEnabled(isEnabled);
                }
            }
        }
    }

    /**
     * Delete button Action Listener ********
     */
    private class DeleteButtonActionListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            //do deleting vocabularies
            int[] selRowIndexes = cardTable.getSelectedRows();
            List<CardBean> delCardList = new ArrayList<CardBean>();
            try {
                for (int i = 0; i < selRowIndexes.length; i++) {
                    CardBean delCard = dataModel.getRowData(selRowIndexes[i]);
                    if (delCard == null) {
                        continue;
                    }
                    ///delete only card that is existing
                    if (delCard.getId() != -1) {
                        cardDao.deleteCardById(delCard.getId());
                    }
                    delCardList.add(delCard);
                }
                //cancel editing
                cardTable.editingCanceled(null);

                //remove card from table
                //cardTable.clearSelection();
                for (CardBean card : delCardList) {
                    dataModel.removeRow(card);
                }
                int rowCount = dataModel.getRowCount();
                if (rowCount > 0) {
                    //select last row
                    cardTable.getSelectionModel().setSelectionInterval(rowCount - 1, rowCount - 1);
                } else {
                    cardTable.clearSelection();
                }
                //update UI
                cardTable.updateUI();

                enableToolBarButton("Add", true);
            } catch (Exception e1) {
                String error = Resources.getString("message.delete.card.error");
                JOptionPane.showMessageDialog(mainPanel.getParent(), error, "Error", JOptionPane.WARNING_MESSAGE);
                e1.printStackTrace();
            }

        }
    }

    /**
     * Help button Action Listener ********
     */
    private class HelpButtonActionListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            String message = Resources.getString("message.editvocab.help");
            JOptionPane.showMessageDialog(mainPanel.getParent(), message, "iFlashCards", JOptionPane.INFORMATION_MESSAGE);
        }
    }

    /**
     * to support accelerator for buttons, subclass AbstractAction
     */
    private class DoneButtonAction extends AbstractAction {
        public void actionPerformed(ActionEvent e) {
            EditVocabularyWindow.this.actionPerformed(e);
        }
    }

    /**
     * new word button
     */
    private class AddButtonAction extends AbstractAction {
        public void actionPerformed(ActionEvent e) {
            //add new word
            new AddButtonActionListener().actionPerformed(null);
        }
    }

    /**
     * delete a word button click
     */
    private class DeleteButtonAction extends AbstractAction {
        public void actionPerformed(ActionEvent e) {
            new DeleteButtonActionListener().actionPerformed(null);
        }
    }
    /********Subclass cell editor ************/
    /**
     * Override to validate whether input word is valid
     * User: hung
     * Date: 2008/05/05
     * Time: 11:48:37
     * To change this template use File | Settings | File Templates.
     */
    public class VocabularyCellEditor extends DefaultCellEditor {

        public VocabularyCellEditor(JTextField textField) {

            super(textField);
            textField.setBorder(new EmptyBorder(0, 0, 0, 0));

        }

        public boolean stopCellEditing() {
            String word = (String) getCellEditorValue();
            if ((null == word || "".equals(word.trim()))) {
                String error = Resources.getString("message.editvocab.blankword.warn");
                JOptionPane.showMessageDialog(mainPanel.getParent(), error, "Warn", JOptionPane.WARNING_MESSAGE);
                //disable add button (to keep current selection)
                enableToolBarButton("Add", false);

                return false;

            }
            enableToolBarButton("Add", true);
            return super.stopCellEditing();
        }
    }

    /**
     * Default cell editor, subclass to be able to select all when got focus
     */
    class DefaultCellTextEditor extends JTextField {
        protected void processFocusEvent(FocusEvent fe) {
            if (fe.getID() == FocusEvent.FOCUS_GAINED) {
                selectAll();
            } else if (fe.getID() == FocusEvent.FOCUS_LOST) {
                select(0, 0);
            }
            super.processFocusEvent(fe);
        }
    }


}
